#include "CSound.h"

namespace Framework
{
	CSound::CSound (HWND hwnd){
		m_hwnd		= hwnd;
		m_device	= -1;
		m_freq		= 44100;
		m_flags		= 0;
	}

	CSound::~CSound (){
		//
	}

	bool	CSound::init (int device, DWORD freqs, DWORD flags){
		m_device	= device;
		m_freq		= freqs;
		m_flags		= flags;

		// Check BASS version
		if (HIWORD(BASS_GetVersion()) != BASSVERSION){
			MessageBoxA(m_hwnd, "An incorrect version of Bass.dll was loaded !", "Error", MB_OK | MB_ICONERROR);
			return false;
		}

		// Init bass
		if (!BASS_Init(m_device, m_freq, m_flags, m_hwnd, 0)){
			return false;
		}

		return true;
	}

	void	CSound::deinitialize (){
		map<string, STREAM_NODE>::iterator str_iter = m_sounds.begin();
		while (str_iter != m_sounds.end()){
			// free all streams
			if (str_iter->second.type == STR_MOD){
				BASS_MusicFree(str_iter->second.hStream);
			} else {
				BASS_StreamFree(str_iter->second.hStream);
			}
			str_iter++;
		}
		m_sounds.clear();					// Clear all node
	}

	bool	CSound::addFile (STREAM_TYPE type, string name, string filename, DWORD flag){
		if (m_sounds.find(name) == m_sounds.end()){			// The name does not exist
			DWORD		hSound	= NULL;
			if (type == STR_MOD){							// MOD format
				// Loads a MOD music file; MO3 / IT / XM / S3M / MTM / MOD / UMX formats.
				hSound = BASS_MusicLoad(FALSE, filename.c_str(), 0, 0, flag, 0);
				if (hSound){
					m_sounds[name].hStream	= hSound;
					m_sounds[name].type		= type;
					return true;
				} else {
					MessageBoxA(m_hwnd, "Bass load file failed !", "Error", MB_OK | MB_ICONERROR);
					return false;
				}
			} else if (type == STR_MP123_OGG_WAV_AIFF){
				// Creates a sample stream from an MP3, MP2, MP1, OGG, WAV, AIFF formats
				hSound = BASS_StreamCreateFile(FALSE, filename.c_str(), 0, 0, flag);
				if (hSound){
					m_sounds[name].hStream	= hSound;
					m_sounds[name].type		= type;
					return true;
				} else {
					MessageBoxA(m_hwnd, "Bass load file failed !", "Error", MB_OK | MB_ICONERROR);
					return false;
				}
			} else {
				MessageBoxA(m_hwnd, "Unsupported format !", "Info", MB_OK | MB_ICONERROR);
				return false;
			}
		} else {											// The name does exist
			return false;
		}
	}

	bool	CSound::remove (string name){
		map<string, STREAM_NODE>::iterator temp = m_sounds.find(name);
		if (temp != m_sounds.end()){			// Sound exist
			// Free sound
			if (temp->second.type == STR_MP123_OGG_WAV_AIFF){
				BASS_StreamFree(temp->second.hStream);
			} else if (temp->second.type == STR_MOD){
				BASS_MusicFree(temp->second.hStream);
			}
			m_sounds.erase(temp);				// Remove node
			return true;
		} else {
			return false;
		}
	}

	bool CSound::play (string name, bool restart){
		map<string, STREAM_NODE>::iterator temp = m_sounds.find(name);
		if (temp != m_sounds.end()){
			if (BASS_ChannelPlay(temp->second.hStream, restart)) {
				return true;
			} else {
				return false;
			}
		} else {
			return false;
		}
	}

	bool CSound::pause (string name){
		map<string, STREAM_NODE>::iterator temp = m_sounds.find(name);
		if (temp != m_sounds.end()){
			if (BASS_ChannelPause(temp->second.hStream)){
				return true;
			} else {
				return false;
			}
		} else {
			return false;
		}
	}

	bool	CSound::stop (string name){
		map<string, STREAM_NODE>::iterator temp = m_sounds.find(name);
		if (temp != m_sounds.end()){
			if (BASS_ChannelStop(temp->second.hStream)){
				return true;
			} else {
				return false;
			}
		} else {
			return false;
		}
	}

	DWORD	CSound::getState (string name){
		map<string, STREAM_NODE>::iterator temp = m_sounds.find(name);
		if (temp != m_sounds.end()){
			return BASS_ChannelIsActive(temp->second.hStream);
		} else {
			return NULL;
		}
	}

	void CSound::pauseAll (){
		BASS_Pause();
	}

	void CSound::stopAll (){
		BASS_Stop();
	}

	void CSound::resumeAll (){
		BASS_Start();
	}

	void CSound::setGlobalVolume (int val){
		BASS_SetVolume(float(val)/100.0f);
	}

	void CSound::setItemVolume (string name, int val){
		map<string, STREAM_NODE>::iterator temp = m_sounds.find(name);
		if (temp != m_sounds.end()){
			BASS_ChannelSetAttribute(temp->second.hStream, BASS_ATTRIB_VOL, float(val)/100.0f);
		}
	}

}